package com.example.base.aop.permission

import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.commit

/**  权限请求工具类  **/
class PermissionTool private constructor(val activity: FragmentActivity) {

    companion object {
        /**  请求权限的请求码  **/
        const val REQUEST_PERMISSION_CODE = 9 shl 4

        /**  请求权限的 Fragment 的标签  **/
        private const val fragmentTag = "requestPermissionFragment"

        fun getInstance(activity: FragmentActivity) = PermissionTool(activity)
    }

    /**  待申请的权限列表  **/
    private var permissions: Array<out String> = emptyArray()

    /**  负责申请权限的 Fragment  **/
    private var requestPermissionFragment: RequestPermissionFragment? = null

    /**  请求目标权限组  **/
    fun request(permissions: Array<out String>): PermissionTool {
        this.permissions = permissions
        return this
    }

    @Throws(PermissionRequestException::class)
    fun execute(requestPermissionCallback: RequestPermissionCallback) {
        // 1.首先检查动态申请的权限是否都在清单文件中注册
        checkManifestPermissions()

        // 2.若所申请的动态权限之前都已授权, 则无需进行重新申请
        if (getUserNotGrantedPermissions().isEmpty()) {
            requestPermissionCallback.onSuccess()
            return
        }

        // 3.准备申请动态权限的 Fragment
        prepareFragment(requestPermissionCallback)

        // 4.申请动态权限
        requestPermissions()
    }

    /** 检测是否存在未在清单文件中注册的权限  **/
    @Throws(PermissionRequestException::class)
    private fun checkManifestPermissions() {
        if (permissions.isEmpty())
            throw PermissionRequestException("You not have request permissions!")

        val notRegisterPermissions = getNotRegisterPermissions()
        if (notRegisterPermissions.isNotEmpty()) {
            val buffer = StringBuffer("申请动态权限需要同时在清单文件中进行注册！您当前未注册的权限有")
            notRegisterPermissions.forEach { notRegisterPermission ->
                buffer.append(" [").append(notRegisterPermission).append("] ")
            }
            buffer.append("请您去清单文件中进行注册后重试！")
            Log.e("PermissionRequestError", buffer.toString())
            throw PermissionRequestException("Not register permissions in Manifest!")
        }
    }

    /**  获取用户未授权的权限列表  **/
    fun getUserNotGrantedPermissions(): Array<out String> {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return emptyArray()

        // 筛选 需要申请的权限
        return permissions.filter { permission ->
            ContextCompat.checkSelfPermission(
                activity,
                permission
            ) != PackageManager.PERMISSION_GRANTED
        }.toTypedArray()
    }

    /**  准备用于申请动态权限的 Fragment  **/
    private fun prepareFragment(requestPermissionCallback: RequestPermissionCallback) {
        val fragmentManager = activity.supportFragmentManager
        val fragment = fragmentManager.findFragmentByTag(fragmentTag)
        if (null == fragment) {
            requestPermissionFragment = RequestPermissionFragment()
            fragmentManager.commit {
                add(requestPermissionFragment!!, fragmentTag)
            }
            fragmentManager.executePendingTransactions()
        } else requestPermissionFragment = (fragment as RequestPermissionFragment)
        requestPermissionFragment!!.requestPermissionCallback = requestPermissionCallback
    }

    /**  获取开发者动态申请却没在清单文件中注册的权限列表  **/
    private fun getNotRegisterPermissions(): List<String> {
        val registerPermissions = getRegisterPermissions()
        return permissions.filter { permission ->
            registerPermissions.contains(permission).not()
        }
    }

    /**  获取在自己 App 中清单文件所注册了的权限列表  **/
    private fun getRegisterPermissions(): Array<out String> {
        val packageInfo = activity.packageManager.getPackageInfo(
            activity.packageName,
            PackageManager.GET_PERMISSIONS
        )
        return packageInfo.requestedPermissions ?: emptyArray()
    }

    /**  获取目标权限的名称, 失败时则返回空串  **/
    fun getPermissionName(targetPermission: String): String {
        try {
            val packageManager = activity.packageManager
            val permissionInfo = packageManager.getPermissionInfo(targetPermission, 0)
            val groupInfo = packageManager.getPermissionGroupInfo(permissionInfo.group ?: "", 0)
            return groupInfo.loadLabel(packageManager).toString()
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
        return ""
    }

    /**  申请动态权限  **/
    private fun requestPermissions() {
        requestPermissionFragment?.apply {
            permissions = this@PermissionTool.permissions
            resetRequestTime()
            try {
                requestPermissions(permissions, REQUEST_PERMISSION_CODE)
            } catch (e: IllegalStateException) {
                showHintDialog()
            }
        }
    }

}